package com.micro.platform.starter.config.lock;

import com.micro.platform.starter.utils.RandomUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 分布式锁注解处理切面
 */

@Slf4j
@Aspect
@Component
public class DistributedLockAspect {

    @Autowired
    private LockComponent lock;

    /**
     * 在方法上执行同步锁
     */
    @Around(value = "@annotation(lockable)")
    public Object distLock(ProceedingJoinPoint point, DistributedLockable lockable) throws Throwable {
        boolean locked = false;
        String charAndNumr = RandomUtils.getCharAndNumr(10);
        String key = lockable.prefix() + lockable.key();
        try {
            locked = lock.lock(key, charAndNumr, lockable.expire());
            if(locked) {
                return point.proceed();
            } else {
                log.info("Did not get a lock for key {}", key);
                return null;
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if(locked) {
                if(!lock.unLock(key, charAndNumr)){
                    log.warn("Unlock {} failed, maybe locked by another client already. ", lockable.key());
                }
            }
        }
    }
}
